package cn.tpshion.devops.node;

import cn.tpshion.devops.common.constant.NodeConstant;
import cn.tpshion.devops.common.enums.MsgType;
import cn.tpshion.devops.common.enums.NodeType;
import cn.tpshion.devops.domain.entity.MsgData;
import cn.tpshion.devops.domain.entity.NodeData;
import cn.tpshion.devops.handle.LocalCommandHandle;
import cn.tpshion.devops.node.data.GradleData;
import cn.tpshion.devops.node.support.NodeContext;
import cn.tpshion.devops.util.AssertUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class GradleNode extends Node<GradleData>{

    @Value("${node.gradleHome}")
    private String gradleHome;

    @Override
    public NodeType nodeType() {
        return NodeType.GRADLE;
    }

    @Override
    public void handle(NodeContext nodeContext) throws Exception {
        log.info("GradleNode nodeContext:{}", nodeContext);
        sseHandle.sendMessage(nodeContext, new MsgData(MsgType.INFO, "开始执行gradle节点"));

        Map<String, Object> contextData = nodeContext.getData();
        String workspace = contextData.get(NodeConstant.WORKSPACE).toString();

        GradleData data = getData(nodeContext);

        String commandStr = handleCommandStr(data.getCommand(), workspace);
        AssertUtil.isEmpty(commandStr, "命令错误");

        sseHandle.sendMessage(nodeContext, new MsgData(MsgType.INFO, "执行命令：" + commandStr));
        LocalCommandHandle commandHandle = new LocalCommandHandle(sseHandle, nodeContext, workspace);
        commandHandle.exec(commandStr);
    }

    private String handleCommandStr(String command, String workspace){
        if(!StringUtils.hasText(command)){
            return null;
        }

        if(command.contains("#workspace#")){
            command = command.replaceAll("#workspace#", workspace);
        }

        if(command.contains("#gradleHome#")){
            command = command.replaceAll("#gradleHome#", gradleHome);
        }

        List<String> list = Arrays.stream(StringUtils.delimitedListToStringArray(command, "\n"))
                .filter(i -> StringUtils.hasText(i)).collect(Collectors.toList());
        if(ObjectUtils.isEmpty(list)){
            return null;
        }

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            builder.append(i == 0 ? list.get(i) : " && " + list.get(i));
        }
        return builder.toString();
    }

    @Override
    protected GradleData getData(NodeContext nodeContext) {
        NodeData nodeData = nodeContext.getNodeData();
        GradleData gradleData = JSON.parseObject(JSON.toJSONString(nodeData.getData()), GradleData.class);
        if(!StringUtils.hasText(gradleData.getGradleHome())){
            gradleData.setGradleHome(gradleHome);
        }
        return gradleData;
    }

    public static void main(String[] args) throws Exception{
        List<String> commandList = new ArrayList<>();
        commandList.add("/bin/sh");
        commandList.add("-c");
        commandList.add("/Users/chen/Downloads/tools/gradle-8.4/bin/gradle -v && /Users/chen/Downloads/tools/gradle-8.4/bin/gradle task bootJar");

        log.info("LocalCommandHandle commandList:{}", commandList);
        ProcessBuilder processBuilder = new ProcessBuilder(commandList);
        processBuilder.directory(new File("/Users/chen/Downloads/workspace/gradle-demo"));
        Process process = processBuilder.start();

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))){
            String line;
            while ((line = reader.readLine()) != null) {
                log.info("LocalCommandHandle exec log:{}", line);
            }

            int exitCode = process.waitFor();
            log.info("LocalCommandHandle exec exitCode:{}", exitCode);
            AssertUtil.isTrue(exitCode != 0 && exitCode != -1, "命令执行失败");
        }
    }
}
